/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.framework;

import java.util.ArrayList;
import java.util.List;

import org.springframework.util.Assert;

/**
 * Base class for proxy factories.
 * Provides convenient access to a configurable AopProxyFactory.
 *
 * @author Juergen Hoeller
 * @since 2.0.3
 * @see #createAopProxy()
 */

/**
 1. 总结
 ProxyCreatorSupport 是 Spring AOP 框架中的代理工厂基类
	 提供了对可配置 AopProxyFactory 的便捷访问
	 支持监听器机制，可以注册 AdvisedSupportListener 来监听代理创建和通知变化
	 管理代理激活状态，确保代理创建的一致性

 2. 内部成员详解
 成员变量
	 aopProxyFactory: AopProxyFactory 类型，用于创建 AOP 代理实例
	 listeners: List<AdvisedSupportListener> 类型，存储注册的监听器
	 active: boolean 类型，标记是否已创建第一个 AOP 代理
 方法
	 ProxyCreatorSupport(): 默认构造函数，使用 DefaultAopProxyFactory
	 ProxyCreatorSupport(AopProxyFactory aopProxyFactory): 带参数构造函数，指定 AopProxyFactory
	 setAopProxyFactory(AopProxyFactory aopProxyFactory): 设置 AopProxyFactory
	 getAopProxyFactory(): 获取当前使用的 AopProxyFactory
	 addListener(AdvisedSupportListener listener): 添加监听器
	 removeListener(AdvisedSupportListener listener): 移除监听器
	 createAopProxy(): 创建 AOP 代理（同步方法）
	 activate(): 激活代理配置，通知所有监听器
	 adviceChanged(): 通知监听器通知变更
	 isActive(): 检查是否已激活（同步方法）

 3 和其他的接口和类之间的关系
 ProxyConfig (class)
 └── AdvisedSupport (class)
	 └── ProxyCreatorSupport (class)
			 └──AspectJProxyFactory (class)
			 └──ProxyFactory (class)
			 └──ProxyFactoryBean (class)


 相关类和接口说明
	 AopProxyFactory: 创建 AOP 代理的工厂接口，ProxyCreatorSupport 通过它来创建代理
	 AdvisedSupportListener: 监听器接口，用于监听代理配置的激活和通知变更事件
	 AdvisedSupport: 父类，提供通知(advice)管理的基本功能

 ProxyCreatorSupport的3个子类的区别
	 1. ProxyFactory
		 特点：
			 通用性强：是最常用的代理工厂类，适用于大多数程序化创建AOP代理的场景
			 构造灵活：提供多种构造函数，支持基于目标对象、接口、拦截器等方式创建代理
			 使用简便：提供了静态方法便于快速创建代理
		 主要用途：
			 程序化创建AOP代理（不依赖Spring容器）
			 测试环境中快速创建代理对象
			 自定义AOP解决方案

	 2. ProxyFactoryBean
		 特点：
			 集成Spring容器：作为Spring Bean工厂的一部分，通过IoC容器管理
			 声明式配置：可以通过XML或注解方式进行配置
			 生命周期管理：遵循Spring Bean的生命周期
		 主要用途：
			 在Spring应用上下文中声明式地创建AOP代理
			 与其他Spring组件无缝集成
			 支持复杂的代理配置场景

	 3. AspectJProxyFactory
		 特点：
			 AspectJ集成：专门用于处理AspectJ风格的切面编程
			 注解支持：天然支持@Aspect、@Before、@After等AspectJ注解
			 混合模型：可以在Spring AOP框架内使用AspectJ切面
		 主要用途：
			 使用AspectJ注解定义切面的场景
			 需要AspectJ强大切点表达式的应用
			 将AspectJ切面集成到Spring AOP中





 4. 使用场景
	 自定义代理工厂: 当需要创建自定义的代理工厂时，可以继承此类
	 代理创建监听: 需要监听代理创建过程或通知变更时
	 AOP框架扩展: 作为Spring AOP框架的基础类，为其他代理创建类提供通用功能
	 集成第三方代理机制: 可以通过替换 AopProxyFactory 来集成不同的代理创建机制

 5. 实际代码应用示例
 ==============案例1
 // 创建 ProxyCreatorSupport 实例
 ProxyCreatorSupport proxyCreator = new ProxyCreatorSupport();

 // 添加自定义监听器
 proxyCreator.addListener(new AdvisedSupportListener() {
	@Override
	public void activated(AdvisedSupport advised) {
		System.out.println("Proxy activated");
	}

	@Override
	public void adviceChanged(AdvisedSupport advised) {
	System.out.println("Advice changed");
	}
});

 // 设置目标对象和通知
 proxyCreator.setTarget(new MyTargetObject());
 proxyCreator.addAdvice(new MyMethodInterceptor());

 // 创建代理
 AopProxy aopProxy = proxyCreator.createAopProxy();
 Object proxy = aopProxy.getProxy();

 // 检查是否激活
 boolean isActive = proxyCreator.isActive();



 */
@SuppressWarnings("serial")
public class ProxyCreatorSupport extends AdvisedSupport {

	private AopProxyFactory aopProxyFactory;

	private final List<AdvisedSupportListener> listeners = new ArrayList<>();

	/** Set to true when the first AOP proxy has been created. */
	private boolean active = false;


	/**
	 * Create a new ProxyCreatorSupport instance.
	 */
	public ProxyCreatorSupport() {
		this.aopProxyFactory = new DefaultAopProxyFactory();
	}

	/**
	 * Create a new ProxyCreatorSupport instance.
	 * @param aopProxyFactory the AopProxyFactory to use
	 */
	public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
		Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
		this.aopProxyFactory = aopProxyFactory;
	}


	/**
	 * Customize the AopProxyFactory, allowing different strategies
	 * to be dropped in without changing the core framework.
	 * <p>Default is {@link DefaultAopProxyFactory}, using dynamic JDK
	 * proxies or CGLIB proxies based on the requirements.
	 */
	public void setAopProxyFactory(AopProxyFactory aopProxyFactory) {
		Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
		this.aopProxyFactory = aopProxyFactory;
	}

	/**
	 * Return the AopProxyFactory that this ProxyConfig uses.
	 */
	public AopProxyFactory getAopProxyFactory() {
		return this.aopProxyFactory;
	}

	/**
	 * Add the given AdvisedSupportListener to this proxy configuration.
	 * @param listener the listener to register
	 */
	public void addListener(AdvisedSupportListener listener) {
		Assert.notNull(listener, "AdvisedSupportListener must not be null");
		this.listeners.add(listener);
	}

	/**
	 * Remove the given AdvisedSupportListener from this proxy configuration.
	 * @param listener the listener to deregister
	 */
	public void removeListener(AdvisedSupportListener listener) {
		Assert.notNull(listener, "AdvisedSupportListener must not be null");
		this.listeners.remove(listener);
	}


	/**
	 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
	 * create an AOP proxy with {@code this} as an argument.
	 */
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		// 默认为DefaultAopProxyFactory
		return getAopProxyFactory().createAopProxy(this);
	}

	/**
	 * Activate this proxy configuration.
	 * @see AdvisedSupportListener#activated
	 */
	private void activate() {
		this.active = true;
		for (AdvisedSupportListener listener : this.listeners) {
			listener.activated(this);
		}
	}

	/**
	 * Propagate advice change event to all AdvisedSupportListeners.
	 * @see AdvisedSupportListener#adviceChanged
	 */
	@Override
	protected void adviceChanged() {
		super.adviceChanged();
		synchronized (this) {
			if (this.active) {
				for (AdvisedSupportListener listener : this.listeners) {
					listener.adviceChanged(this);
				}
			}
		}
	}

	/**
	 * Subclasses can call this to check whether any AOP proxies have been created yet.
	 */
	protected final synchronized boolean isActive() {
		return this.active;
	}

}
